package com.hxk.juc;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 什么事CAS？
 *      CAS比较并交换（compareAndSet）是一种很重要的同步思想。如果主内存的值跟期望值一样，那么就进行修改，否则一直重试，直到一致为止
 * 哪里使用CAS：
 *      java的juc下的java.util.concurrent.atomic包下的所有原子类都是使用volatile+cas实现数据在多线程下的原子性
 * 那么CAS的底层又是怎么实现数据的++操作的？
 *      unsafe+dowhile（自旋锁实现），具体底层源码如下：
 *      public final int getAndAddInt(Object var1, long var2, int var4) {
            int var5;
             do {
                var5 = this.getIntVolatile(var1, var2);
             } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));//底层是汇编语言编写的cup原语
             return var5;
        }
        这个方法的var1和var2，就是根据【对象】和【偏移量】得到在【主内存的快照值】var5。然后`compareAndSwapInt`方法通过var1和var2得到当前【主内存的实际值】。如果这个【实际值】跟【快照值】相等，那么就更新主内存的值为var5+var4。如果不等，那么就一直循环，一直获取快照，一直对比，直到实际值和快照值相等为止。
        比如有A、B两个线程，一开始都从主内存中拷贝了原值为3，A线程执行到`var5=this.getIntVolatile`，即var5=3。此时A线程挂起，B修改原值为4，B线程执行完毕，由于加了volatile，所以这个修改是立即可见的。A线程被唤醒，执行`this.compareAndSwapInt()`方法，发现这个时候主内存的值不等于快照值3，所以继续循环，【重新】从主内存获取。
    CAS的优点和缺点：
        优点：
            提高了并发量
        缺点：
            1、因为dowhile对（自旋锁），加大了cpu的开销
            2、只能保证一个变量的原子性，不能保证多个
            3、有ABA（时间差）问题
 */
public class CASCase {

    public static void main(String[] args) {

        AtomicInteger atomicInteger = new AtomicInteger(3);

        System.out.println(atomicInteger.compareAndSet(3, 5)+" 当前值："+atomicInteger.get());

        System.out.println(atomicInteger.compareAndSet(3, 10)+"当前值："+atomicInteger.get());

    }
}
